<template>
  <div>
    <el-form-item label="方法类型">
      <el-row>
        <el-col :span="14">
          <el-radio-group v-model="baseSetting.httpMethod" class="width-100" @change="forceUpdates">
            <el-radio :label="func.value" :key="idx" v-for="(func, idx) in commonConfig.httpMethod">{{func.label}}
            </el-radio>
          </el-radio-group>
        </el-col>
        <el-col :span="10" class="text-align-right">
          <el-button type="success" size="small" @click="clickCommandValidate('encode')">编码校验</el-button>
          <el-button type="primary" size="small" @click="clickCommandValidate('decode')">解码校验</el-button>
        </el-col>
      </el-row>
    </el-form-item>
    <el-form-item label="ContentType">
      <el-select v-model="baseSetting.httpContentType" clearable filterable class="width-100"
                 placeholder="请选择 ContentType" @change="forceUpdates">
        <el-option :label="type.label" :value="type.value" :key="idx"
                   v-for="(type, idx) in commonConfig.httpContentType"></el-option>
      </el-select>
    </el-form-item>
    <el-row>
      <el-col :span="24" class="pad-all-10">
        <div class="col-container">
          <el-form-item label="请求URI" class="mar-btm-0">
            <CommandStreamTag :stream-str-info="httpUrlInfo.httpUrlStr" :stream-tags="httpUrlInfo.httpUrlTagData"
                              @clickCommandTag="clickHttpParamTag"></CommandStreamTag>
          </el-form-item>
        </div>
      </el-col>
      <el-col :span="24" class="pad-all-10">
        <div class="col-container">
          <el-form-item label="Headers" class="mar-btm-0">
            <EnumDynamic title="Header" :isValueStream="true" :dynamic-data="httpHeaders"
                         @clickCommandTag="clickHttpParamTag">
            </EnumDynamic>
          </el-form-item>
        </div>
      </el-col>
      <el-col :span="24" class="pad-all-10">
        <div class="col-container">
          <el-form-item label="Content" class="mar-btm-0">
            <EnumDynamic v-if="baseSetting.httpContentType === commonConfig.httpContentType[0].value" title="Content"
                         :isValueStream="true" :dynamic-data="httpContent" @clickCommandTag="clickHttpParamTag">
            </EnumDynamic>
            <CommandStreamTag v-if="[commonConfig.httpContentType[1].value,commonConfig.httpContentType[2].value].includes(baseSetting.httpContentType )"
                              input-type="textarea" :stream-str-info="httpContentInfo.httpContentStr"
                              :stream-tags="httpContentInfo.httpContentTagData"
                              @clickCommandTag="clickHttpParamTag"></CommandStreamTag>
          </el-form-item>
        </div>
      </el-col>
      <el-col :span="24" class="pad-all-10">
        <div class="col-container">
          <el-form-item label="Response" class="mar-btm-0">
            <EnumDynamic v-if="baseSetting.httpContentType === commonConfig.httpContentType[0].value" title="Rsp"
                         :isValueStream="true" :dynamic-data="httpResponse" @clickCommandTag="clickHttpParamTag">
            </EnumDynamic>
            <CommandStreamTag v-if="[commonConfig.httpContentType[1].value,commonConfig.httpContentType[2].value].includes(baseSetting.httpContentType )"
                              input-type="textarea" :stream-str-info="httpResponseInfo.httpResponseStr"
                              :stream-tags="httpResponseInfo.httpResponseTagData" @clickCommandTag="clickHttpParamTag">
            </CommandStreamTag>
          </el-form-item>
        </div>
      </el-col>
      <el-col :span="24" class="pad-all-10">
        <div class="col-container">
          <el-row>
            <el-col :span="12"> <el-form-item label="鉴权是否有效函数">
              <el-select v-model="authenticationConfig.checkFunc" clearable filterable class="width-100"
                         placeholder="请选择鉴权函数">
                <el-option label="无" value=""></el-option>
                <el-option :label="func.name" :value="func._id" :key="idx" v-for="(func, idx) in analyzeFuncData">
                </el-option>
              </el-select>
            </el-form-item></el-col>
            <el-col :span="12"> <el-form-item label="鉴权处理函数">
              <el-select v-model="authenticationConfig.authFunc" clearable filterable class="width-100"
                         placeholder="请选择鉴权处理函数">
                <el-option label="无" value=""></el-option>
                <el-option :label="func.name" :value="func._id" :key="idx" v-for="(func, idx) in analyzeFuncData">
                </el-option>
              </el-select>
            </el-form-item></el-col>
          </el-row>
        </div>
      </el-col>
    </el-row>

    <el-dialog title="码流模板校验" :visible.sync="showCommValDialog" width="650px" append-to-body center  :close-on-click-modal="false"
               @close="clearInit">
      <el-form v-loading="commValFormLoading" :model="commValForm" :rules="commValFormRules" size="small"
               :ref="commValFormRef" label-width="130px">
        <el-form-item label="命令名称">
          <el-select v-model="genCommInfo._id" class="width-100" :disabled="true">
            <el-option :label="genComm.label" :value="genComm.value" :key="idx" v-for="(genComm, idx) in genCommData">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="码流模板">
          <el-input :value="JSON.stringify(stream,null,4)" type="textarea" :rows="6"></el-input>
        </el-form-item>
        <div v-if="validateType === commonConfig.analyzeFuncType[0].value">
          <div v-if="commValFormStructure.length > 0" class="param-container">
            <el-form-item :label="item.label" v-for="(item, idx) in commValFormStructure" :key="idx" class="mar-btm-10">
              <el-select v-if="item.type === 'select'" v-model="commValForm[item.prop]" clearable filterable
                         class="width-100">
                <el-option :label="opt.key" :value="opt.key" :key="idx" v-for="(opt, idx) in item.options"></el-option>
              </el-select>
              <el-input v-if="item.type === 'input'" v-model="commValForm[item.prop]"></el-input>
              <el-input-number v-if="item.type === 'input-number'" v-model="commValForm[item.prop]" :min="item.min"
                               :max="item.max" class="width-100"></el-input-number>
            </el-form-item>
          </div>
        </div>
        <div v-if="validateType === commonConfig.analyzeFuncType[1].value">
          <el-form-item label="码流值" prop="contentValue">
            <el-input v-model="commValForm.contentValue" type="textarea" :rows="6" placeholder="请输入 content">
              <el-button slot="append" @click="clickTrimBtn">trim</el-button>
            </el-input>
          </el-form-item>
        </div>
        <el-form-item label="解析结果">
          <el-input v-model="valResult" type="textarea" :rows="5"></el-input>
        </el-form-item>

        <div class="text-align-right">
          <el-form-item>
            <el-button size="medium" @click="commValFormCanceled">取消</el-button>
            <el-button size="medium" type="primary" @click="commValFormSubmitted">提交</el-button>
          </el-form-item>
        </div>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>
  import {commonConfig} from "@/config/common";
  import {msgCode} from "@/config/string";
  import EnumDynamic from "../../../../components/EnumDynamic";
  import CommandStreamTag from '../../../../components/CommandStreamTag';
  import objectPath from 'object-path'
  import {JSONParse} from "@/utils";

  export default {
    name: "HttpSetting",
    components: {
      EnumDynamic, CommandStreamTag
    },
    props: {
      baseSetting: {
        default: () => {
          return {
            httpMethod: commonConfig.httpMethod[0].value,
            httpContentType: commonConfig.httpContentType[0].value,
          }
        }
      },
      httpUrlInfo: {
        default: () => {
          return {
            httpUrlStr: {
              identify: 'Url',
              value: '',
              size: 'medium',
              placeholder: 'url'
            },
            httpUrlTagData: [],
          }
        }
      },
      httpHeaders: {
        default: () => {
          return []
        }
      },
      // application/json 情况
      httpContent: {
        default: () => {
          return []
        }
      },
      httpResponse: {
        default: () => {
          return []
        }
      },
      // http text/html 情况
      httpContentInfo: {
        default: () => {
          return {
            httpContentStr: {
              identify: 'Content',
              value: '',
              size: 'medium',
              placeholder: 'content xml'
            },
            httpContentTagData: [],
          }
        }
      },
      httpResponseInfo: {
        default: () => {
          return {
            httpResponseStr: {
              identify: 'Rsp',
              value: '',
              size: 'medium',
              placeholder: 'response xml'
            },
            httpResponseTagData: [],
          }
        }
      },

      // 模流模板校验相关
      genCommInfo: {
        default: () => {
          return {}
        }
      },
      decodeFunc: {
        default: () => {
          return ''
        }
      },
      encodeFunc: {
        default: () => {
          return ''
        }
      },
      //鉴权
      authenticationConfig: {
        default: () => {
          return {
            checkFunc:'',
            authFunc:''
          }
        }
      },
    },
    data() {
      const checkJson = (rule, value, callback) => {
        try {
          JSON.parse(value);
        } catch (e) {
          console.log("json 格式错误")
          callback(new Error('json格式错误'));
        }
        callback()
      }
      return {
        commonConfig: commonConfig,
        showCommValDialog: false,
        commValFormLoading: false,
        commValFormStructure: [],
        commValForm: {contentValue: ''},
        commValFormRules: {
          contentValue: [
            {validator: checkJson, message: "请输入正确的json格式且不能为空", trigger: "blur"}
          ],
        },
        commValParams: {},
        commValParamSchema: {},
        genCommData: [],
        analyzeFuncData: [],

        validateType: '',
        stream: {
          uri: '',
          method: '',
          contentType: '',
          header: {},
          content: {},
          response: {},
        },
        customFunc: '',
        // contentValue: '', // decode 输入的 content
        valResult: '',
        encodeFuncT: '',
        decodeFuncT: '',
        commValFormRef: ''

      }
    },
    created() {
      this.getGenCommData();
      this.getAnalyzeFuncData();
    },
    methods: {
      forceUpdates() {
        this.$forceUpdate()
      },
      clearInit() {
        this.commValForm.contentValue = ""
      },
      getCodeFunc() {
        //解析编码解码对应的函数
        API.analyzeFunc.analyzeFuncList({pageNo: 1, pageSize: 1000}).then(result => {
          const {data = []} = result;
          if (this.decodeFunc) {
            var decode = data.filter(item => {
              return item._id == this.decodeFunc
            })
            this.decodeFuncT = decode ? decode[0].function : ''
          }
          if (this.encodeFunc) {
            var encode = data.filter(item => {
              return item._id == this.encodeFunc
            })
            this.encodeFuncT = encode ? encode[0].function : ''
          }
        }).catch(err => {
          console.log('err', err)
        });
      },
      clickHttpParamTag(type = '', tag = {}) {
        this.$emit('clickHttpParamTag', type, tag);
      },
      getGenCommData() {
        API.genCommand.genCommAll().then(result => {
          const {data = []} = result;
          this.genCommData = data;
        }).catch(err => {
          console.log('err', err)
        });
      },
      getAnalyzeFuncData() {
        API.analyzeFunc.analyzeFuncList({pageNo: 1, pageSize: 1000}).then(result => {
          const {data = []} = result;
          this.analyzeFuncData = data;
        }).catch(err => {
          console.log('err', err)
        });
      },
      getAnalyzeFuncData1() {
        API.analyzeFunc.analyzeFuncAll().then(result => {
          const {data = []} = result;
          this.analyzeFuncData = data;
        }).catch(err => {
          console.log('err', err)
        });
      },
      clickTrimBtn() {
        this.commValForm.contentValue = this.commValForm.contentValue.replace(/\s/g, "");
      },
      clickCommandValidate(validateType) {
        // console.log('##### baseSetting #####', this.baseSetting);
        // console.log('##### httpUrlInfo #####', this.httpUrlInfo);
        // console.log('##### httpHeaders #####', this.httpHeaders);
        // console.log('##### httpContent #####', this.httpContent);
        // console.log('##### httpResponse #####', this.httpResponse);
        // console.log('##### httpContentInfo #####', this.httpContentInfo);
        // console.log('##### httpResponseInfo #####', this.httpResponseInfo);
        // console.log('##### genCommInfo #####', this.genCommInfo);
        this.validateType = validateType;
        this.valResult = '';
        const commValForm = {};
        this.commValForm = {};
        this.commValParams = {};
        this.commValParamSchema = {};
        this.commValFormStructure = [];
        const {statusParams = [], controlParams = []} = this.genCommInfo;
        this.stream = {
          uri: this.httpUrlInfo.httpUrlStr.value,
          method: this.baseSetting.httpMethod,
          contentType: this.baseSetting.httpContentType,
          header: {},
          content: {},
          response: {},
        };
        this.customFunc = {};
        const getParamFromGenComm = (value) => {
          return (this.validateType === commonConfig.analyzeFuncType[0].value
            ? controlParams : statusParams).find(s => {
            return s.paramKey === value
          }) || {};
        };
        const getAnalyzeFunc = (func = '') => {
          const funcInfo = this.analyzeFuncData.find(af => {
            return af._id === func
          }) || {};
          return funcInfo.function || ''
        };
        const assembleStream = (src = [], type = '') => {
          src.forEach(s => {
            const {key = '', value = {}} = s;
            const {valueStreamInfo = {}, valueTagData = []} = value;
            if (valueTagData.length > 0) {
              valueTagData.forEach(t => {
                if (t.commandMap) {
                  const {analyzeFunc} = t.commandMap;
                  !analyzeFunc && (objectPath.set(this.stream[type], key, valueStreamInfo.value || ''));
                }
              })
            } else {
              objectPath.set(this.stream[type], key, valueStreamInfo.value || '');
            }
          });
        };
        assembleStream(this.httpHeaders, 'header');
        switch (this.baseSetting.httpContentType) {
          case commonConfig.httpContentType[0].value:
            assembleStream(this.httpContent, 'content');
            assembleStream(this.httpResponse, 'response');
            break;
          case commonConfig.httpContentType[1].value:
            break;
          default:
            break;
        }
        const getHttpParams = (src = []) => {
          const params = src.map(s => {
            const {valueTagData = []} = s.value || {};
            return valueTagData
          });
          return _.flatten(params) || []
        };
        const headersParams = getHttpParams(this.httpHeaders);
        const contentParams = getHttpParams(this.httpContent);
        const responseParams = getHttpParams(this.httpResponse);
        const params = _.union(
          this.httpUrlInfo.httpUrlTagData, headersParams, contentParams, responseParams,
          this.httpContentInfo.httpContentTagData, this.httpResponseInfo.httpResponseTagData
        );
        console.log('##### params #####', params);
        params.forEach(s => {
          // 地址标签需要手动填入参数
          if (s.type === commonConfig.codeTagType.address) {
            this.commValFormStructure.push({
              type: 'input',
              prop: 'address',
              label: '地址',
            });
            commValForm['address'] = '';
          }
          if (s.commandMap) {
            const {
              paramName, dataType, dataLen, byteOrder,
              scale, unit, enumList, field, mapWay, analyzeFunc
            } = s.commandMap;
            // 解析方法的处理
            if (analyzeFunc) {
              this.customFunc[s.value] = getAnalyzeFunc(analyzeFunc);
            } else {
              const paramInfo = getParamFromGenComm(paramName);
              this.commValParams[s.key] = paramName;
              this.commValParamSchema[paramName] = {
                propertyName: paramName,
                dataType, dataLen,
                byteOrder, scale, unit,
              };
              switch (mapWay) {
                case commonConfig.commandMapWay[1].value:
                  this.commValFormStructure.push({
                    type: enumList.length > 0 ? 'select' : 'input',
                    prop: paramName,
                    label: paramInfo.paramAlias || paramName,
                    options: enumList
                  });
                  commValForm[paramName] = '';
                  enumList.length > 0 && (this.commValParamSchema[paramName]['enumList'] = enumList);
                  break;
                case commonConfig.commandMapWay[2].value:
                  const {preMin = 0, preMax = 100} = field;
                  this.commValFormStructure.push({
                    type: 'input-number',
                    prop: paramName,
                    label: paramInfo.paramAlias || paramName,
                    min: preMin,
                    max: preMax,
                  });
                  commValForm[paramName] = 0;
                  this.commValParamSchema[paramName]['field'] = JSON.stringify(field);
                  break;
                default:
                  break;
              }
            }
          }
        });
        this.$set(this, 'commValForm', commValForm);
        this.getCodeFunc()
        this.showCommValDialog = true;
      },
      commValFormCanceled() {
        this.showCommValDialog = false;
      },
      commValFormSubmitted() {
        this.$refs[this.commValFormRef].validate((valid) => {
          if (!valid) return;
          let reqParams = {};
          switch (this.validateType) {
            case commonConfig.analyzeFuncType[0].value:
              reqParams = {
                method: 'httpEncode',
                data: {
                  params: this.commValForm,
                  paramKeyMap: this.commValParams,
                  paramSchemas: this.commValParamSchema,
                  stream: JSON.stringify(this.stream),
                  command_spec: this.stream,
                  custom_func: this.customFunc,
                  encodeFunc: this.encodeFuncT
                },
              };
              break;
            case commonConfig.analyzeFuncType[1].value:
              reqParams = {
                method: 'httpDecode',
                data: {
                  general_command_no: this.genCommInfo.generalCommandNo,
                  paramKeyMap: this.commValParams,
                  paramSchemas: this.commValParamSchema,
                  stream: JSON.stringify(this.stream.response),
                  content: JSON.parse(this.commValForm.contentValue || '{}'),
                  decodeFunc: this.decodeFuncT
                },
              };
              break;
            default:
              break;
          }
          console.log('##### reqParams #####', reqParams);
          this.commValFormLoading = true;
          API.command.commandCheck(reqParams).then(resp => {
            this.commValFormLoading = false;
            const {data = {}} = resp;
            switch (this.validateType) {
              case commonConfig.analyzeFuncType[0].value:
                data.content = typeof data.content == "string" ? JSON.parse(data.content) : data.content;
                //data.content = JSON.parse(data.content) ||  data.content;
                this.valResult = JSON.stringify(data, null, 4)
                break;
              case commonConfig.analyzeFuncType[1].value:
                this.valResult = JSON.stringify(data, null, 4)
                break;
              default:
                break;
            }
          }).catch(err => {
            this.commValFormLoading = false;
            console.log('err: ', err);
          });
          //  this.commValFormLoading = true;
          //   Meteor.call('command_validate', reqParams, (err, result) => {
          //     this.commValFormLoading = false;
          //     if (err) {
          //       console.log('##### err #####', err);
          //       messageHandler({code: msgCode.SYSTEM});
          //     } else {
          //       console.log('##### result #####', result);
          //       const {data = {}} = result;
          //       if (data.errMsg) {
          //         this.$notify({
          //           message: `码流校验失败: ${data.errMsg}`,
          //           type: 'warning',
          //           duration: 3000,
          //         });
          //         return;
          //       }
          //       this.$notify({
          //         message: '码流校验成功',
          //         type: 'success',
          //         duration: 3000,
          //       });
          //       switch (this.validateType) {
          //         case commonConfig.analyzeFuncType[0].value:
          //           data.content = JSON.parse(data.content);
          //           this.valResult = JSON.stringify(data);
          //           break;
          //         case commonConfig.analyzeFuncType[1].value:
          //           this.valResult = JSON.stringify(data);
          //           break;
          //         default:
          //           break;
          //       }
          //     }
          //   })
        })
      },
    },
  }
</script>

<style scoped>
  .col-container {
    border-radius: 8px;
    background: #fafafa;
    padding: 15px;
  }
</style>
